package com.acargil.sudoku.model;

import java.io.Serializable;

import com.acargil.sudoku.model.exception.InvalidCellValueException;
import com.acargil.sudoku.model.exception.InvalidCoordinateException;
import com.acargil.sudoku.model.exception.SudokuValidationException;

/**
 * This is interface only covers the basics of SUDOKU-MODEL.
 * 
 * @author oguzhan
 * */
public interface IStandardSudokuEngine extends Serializable{

	/**
	 * set given value to the cell on (x,y) coordinate
	 * @throws InvalidCellValueException 
	 * @throws InvalidCoordinateException 
	 * */
	void setCellValue(int x, int y, int value) throws InvalidCoordinateException, InvalidCellValueException;

	/**
	 * get given value from the cell on (x,y) coordinate
	 * @throws InvalidCoordinateException 
	 * */
	int getCellValue(int x, int y) throws InvalidCoordinateException;

	/**
	 * Set the value of <code>AbstractSudokuModel.EMPTY_VALUE</code> to the cell
	 * on (x,y) coordinate
	 * @throws InvalidCoordinateException 
	 * */
	void clearCellValue(int x, int y) throws InvalidCoordinateException;

	/**
	 * Set all cells on model to given values
	 * @throws InvalidCellValueException 
	 * */
	void setAllCellValues(int[][] values) throws InvalidCellValueException;

	/**
	 * Get values of all cells from model
	 * */
	int[][] getAllCellValues();

	/**
	 * Set all cells on model to <code>AbstractSudokuModel.EMPTY_VALUE</code>
	 * value
	 * */
	void clearAllCellValues();

	/**
	 * Check the current state of the game.
	 * 
	 * @return {@link SudokuState} state of the game
	 * @throws SudokuValidationException 
	 */
	String checkStateOfGame();

	void validate() throws SudokuValidationException;
	
	/**
	 * Take back last action
	 * */
	void undoLastMove();

	/**
	 * RE-DO last action 
	 * */
	void redoLastMove();

	/**
	 * Get possibilities of each cell on the board.
	 * 
	 * @return a three dimensional array with possible values of each cell
	 * */	
	int[][][] getPossibilitiesOfAllCells();

	/**
	 * Solving the current puzzle with default algorithm; then returns a candidate solution.
	 * <br/>
	 * This solution is not submitted to model; this is totally independent from model.
	 * 
	 * @return a candidate solution to the puzzle
	 * */
	int[][] solve();

	/**
	 * Solving the current puzzle with defined algorithm; then returns a candidate solution.
	 * <br/>
	 * This solution is not submitted to model; this is totally independent from model.
	 * 
	 * @param algorithm an implementation of puzzle solving algorithm
	 * 
	 * @return a candidate solution to the puzzle
	 * */
	int[][] solve(PuzzleSolvingAlgorithm algorithm);
	
	/**
	 * Generating a candidate SUDOKU puzzle with default algorithm.
	 * <br/>
	 * This solution is not submitted to model; this is totally independent from model.
	 * 
	 * @return a generated candidate puzzle
	 * */
	int[][] generatePuzzle();
	
	/**
	 * Generating a candidate SUDOKU puzzle with given algorithm.
	 * <br/>
	 * This solution is not submitted to model; this is totally independent from model.
	 * 
	 * @param algorithm an implementation of puzzle generation algorithm
	 * 
	 * @return a generated candidate puzzle 
	 * */
	int[][] generatePuzzle(PuzzleGenerationAlgorithm algorithm);

	/**
	 * Checks the board and returns true if there are any filled cell.
	 * 
	 * @return <code>false</code> when the board is clean.
	 * */
	boolean isAnyCellFilled();
	
}